home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / dflat2.zip / MESSAGE.C < prev    next >
Text File  |  1991-04-19  |  15KB  |  465 lines

  1. /* --------- message.c ---------- */
  2.  
  3. #include <stdio.h>
  4. #include <dos.h>
  5. #include <conio.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include "dflat.h"
  9.  
  10. static int px = -1, py = -1;
  11. static int pmx = -1, pmy = -1;
  12. static int mx, my;
  13.  
  14. static int CriticalError;
  15.  
  16. /* ---------- event queue ---------- */
  17. static struct events    {
  18.     MESSAGE event;
  19.     int mx;
  20.     int my;
  21. } EventQueue[MAXMESSAGES];
  22.  
  23. /* ---------- message queue --------- */
  24. static struct msgs {
  25.     WINDOW wnd;
  26.     MESSAGE msg;
  27.     PARAM p1;
  28.     PARAM p2;
  29. } MsgQueue[MAXMESSAGES];
  30.  
  31. static int EventQueueOnCtr;
  32. static int EventQueueOffCtr;
  33. static int EventQueueCtr;
  34.  
  35. static int MsgQueueOnCtr;
  36. static int MsgQueueOffCtr;
  37. static int MsgQueueCtr;
  38.  
  39. static int lagdelay = FIRSTDELAY;
  40.  
  41. static void (interrupt far *oldtimer)(void) = NULL;
  42. WINDOW CaptureMouse = NULLWND;
  43. WINDOW CaptureKeyboard = NULLWND;
  44. static int NoChildCaptureMouse = FALSE;
  45. static int NoChildCaptureKeyboard = FALSE;
  46.  
  47. static int doubletimer = -1;
  48. static int delaytimer  = -1;
  49. static int clocktimer  = -1;
  50.  
  51. WINDOW Cwnd = NULLWND;
  52.  
  53. /* ------- timer interrupt service routine ------- */
  54. static void interrupt far newtimer(void)
  55. {
  56.     if (timer_running(doubletimer))
  57.         countdown(doubletimer);
  58.     if (timer_running(delaytimer))
  59.         countdown(delaytimer);
  60.     if (timer_running(clocktimer))
  61.         countdown(clocktimer);
  62.     oldtimer();
  63. }
  64.  
  65. static char ermsg[] = "Error accessing drive x";
  66.  
  67. /* -------- test for critical errors --------- */
  68. int TestCriticalError(void)
  69. {
  70.     int rtn = 0;
  71.     if (CriticalError)    {
  72.         rtn = 1;
  73.         CriticalError = FALSE;
  74.         if (TestErrorMessage(ermsg) == FALSE)
  75.             rtn = 2;
  76.     }
  77.     return rtn;
  78. }
  79.  
  80. /* ------ critical error interrupt service routine ------ */
  81. static void interrupt far newcrit(IREGS ir)
  82. {
  83.     if (!(ir.ax & 0x8000))     {
  84.         ermsg[sizeof(ermsg) - 2] = (ir.ax & 0xff) + 'A';
  85.         CriticalError = TRUE;
  86.     }
  87.     ir.ax = 0;
  88. }
  89.  
  90. /* ------------ initialize the message system --------- */
  91. void init_messages(void)
  92. {
  93.     resetmouse();
  94.     show_mousecursor();
  95.     px = py = -1;
  96.     pmx = pmy = -1;
  97.     mx = my = 0;
  98.     CaptureMouse = CaptureKeyboard = NULLWND;
  99.     NoChildCaptureMouse = FALSE;
  100.     NoChildCaptureKeyboard = FALSE;
  101.     MsgQueueOnCtr = MsgQueueOffCtr = MsgQueueCtr = 0;
  102.     EventQueueOnCtr = EventQueueOffCtr = EventQueueCtr = 0;
  103.     if (oldtimer == NULL)    {
  104.         oldtimer = getvect(TIMER);
  105.         setvect(TIMER, newtimer);
  106.     }
  107.     setvect(CRIT, newcrit);    
  108.     PostMessage(NULLWND,START,0,0);
  109.     lagdelay = FIRSTDELAY;
  110. }
  111.  
  112. /* ----- post an event and parameters to event queue ---- */
  113. static void PostEvent(MESSAGE event, int p1, int p2)
  114. {
  115.     if (EventQueueCtr != MAXMESSAGES)    {
  116.         EventQueue[EventQueueOnCtr].event = event;
  117.         EventQueue[EventQueueOnCtr].mx = p1;
  118.         EventQueue[EventQueueOnCtr].my = p2;
  119.         if (++EventQueueOnCtr == MAXMESSAGES)
  120.             EventQueueOnCtr = 0;
  121.         EventQueueCtr++;
  122.     }
  123. }
  124.  
  125. /* ------ collect mouse, clock, and keyboard events ----- */
  126. static void near collect_events(void)
  127. {
  128.     struct tm *now;
  129.     static int flipflop = FALSE;
  130.     static char timestr[8];
  131.     int hr, sk;
  132.     static int ShiftKeys = 0;
  133.  
  134.     /* -------- test for a clock event (one/second) ------- */
  135.     if (timed_out(clocktimer))    {
  136.         /* ----- get the current time ----- */
  137.         time_t t = time(NULL);
  138.         now = localtime(&t);
  139.         hr = now->tm_hour > 12 ?
  140.              now->tm_hour - 12 :
  141.              now->tm_hour;
  142.         if (hr == 0)
  143.             hr = 12;
  144.         sprintf(timestr, "%2.2d:%02d", hr, now->tm_min);
  145.         strcpy(timestr+5, now->tm_hour > 11 ? "pm" : "am");
  146.         /* ------- blink the : at one-second intervals ----- */
  147.         if (flipflop)
  148.             *(timestr+2) = ' ';
  149.         flipflop ^= TRUE;
  150.         /* -------- reset the timer -------- */
  151.         set_timer(clocktimer, 1);
  152.         /* -------- post the clock event -------- */
  153.         PostEvent(CLOCKTICK, FP_SEG(timestr), FP_OFF(timestr));
  154.     }
  155.  
  156.     /* --------- keyboard events ---------- */
  157.     if ((sk = getshift()) != ShiftKeys)    {
  158.         ShiftKeys = sk;
  159.         /* ---- the shift status changed ---- */
  160.         PostEvent(SHIFT_CHANGED, sk, 0);
  161.     }
  162.  
  163.     /* ---- build keyboard events for key combinations that
  164.         BIOS doesn't report --------- */
  165.     if (sk & ALTKEY)
  166.         if (inp(0x60) == 14)    {
  167.             while (!(inp(0x60) & 0x80))
  168.                 ;
  169.             PostEvent(KEYBOARD, ALT_BS, sk);
  170.         }
  171.     if (sk & CTRLKEY)
  172.         if (inp(0x60) == 82)    {
  173.             while (!(inp(0x60) & 0x80))
  174.                 ;
  175.             PostEvent(KEYBOARD, CTRL_INS, sk);
  176.         }
  177.  
  178.     /* ----------- test for keystroke ------- */
  179.     if (keyhit())    {
  180.         static int cvt[] = {SHIFT_INS,END,DN,PGDN,BS,'5',
  181.                         FWD,HOME,UP,PGUP};
  182.         int c = getkey();
  183.  
  184.         /* -------- convert numeric pad keys ------- */
  185.         if (sk & (LEFTSHIFT | RIGHTSHIFT))    {
  186.             if (c >= '0' && c <= '9')
  187.                 c = cvt[c-'0'];
  188.             else if (c == '.' || c == DEL)
  189.                 c = SHIFT_DEL;
  190.             else if (c == INS)
  191.                 c = SHIFT_INS;
  192.         }
  193.         /* -------- clear the BIOS readahead buffer -------- */
  194.         *(int far *)(MK_FP(0x40,0x1a)) =
  195.             *(int far *)(MK_FP(0x40,0x1c));
  196.         /* ---- if help key call generic help function ---- */
  197.         if (c == F1)
  198.             HelpFunction();
  199.         else
  200.             /* ------ post the keyboard event ------ */
  201.             PostEvent(KEYBOARD, c, sk);
  202.     }
  203.  
  204.     /* ------------ test for mouse events --------- */
  205.     get_mouseposition(&mx, &my);
  206.     if (mx != px || my != py)  {
  207.         px = mx;
  208.         py = my;
  209.         PostEvent(MOUSE_MOVED, mx, my);
  210.     }
  211.     if (rightbutton())
  212.         PostEvent(RIGHT_BUTTON, mx, my);
  213.     if (leftbutton())    {
  214.         if (mx == pmx && my == pmy)    {
  215.             /* ---- same position as last left button ---- */
  216.             if (timer_running(doubletimer))    {
  217.                 /* -- second click before double timeout -- */
  218.                 disable_timer(doubletimer);
  219.                 PostEvent(DOUBLE_CLICK, mx, my);
  220.             }
  221.             else if (!timer_running(delaytimer))    {
  222.                 /* ---- button held down a while ---- */
  223.                 delaytimer = lagdelay;
  224.                 lagdelay = DELAYTICKS;
  225.                 /* ---- post a typematic-like button ---- */
  226.                 PostEvent(LEFT_BUTTON, mx, my);
  227.             }
  228.         }
  229.         else    {
  230.             /* --------- new button press ------- */
  231.             disable_timer(doubletimer);
  232.             delaytimer = FIRSTDELAY;
  233.             lagdelay = DELAYTICKS;
  234.             PostEvent(LEFT_BUTTON, mx, my);
  235.             pmx = mx;
  236.             pmy = my;
  237.         }
  238.     }
  239.     else
  240.         lagdelay = FIRSTDELAY;
  241.     if (button_releases())    {
  242.         /* ------- the button was released -------- */
  243.         doubletimer = DOUBLETICKS;
  244.         PostEvent(BUTTON_RELEASED, mx, my);
  245.         disable_timer(delaytimer);
  246.     }
  247. }
  248.  
  249. /* ----- post a message and parameters to msg queue ---- */
  250. void PostMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  251. {
  252.     if (MsgQueueCtr != MAXMESSAGES)    {
  253.         MsgQueue[MsgQueueOnCtr].wnd = wnd;
  254.         MsgQueue[MsgQueueOnCtr].msg = msg;
  255.         MsgQueue[MsgQueueOnCtr].p1 = p1;
  256.         MsgQueue[MsgQueueOnCtr].p2 = p2;
  257.         if (++MsgQueueOnCtr == MAXMESSAGES)
  258.             MsgQueueOnCtr = 0;
  259.         MsgQueueCtr++;
  260.     }
  261. }
  262.  
  263. /* --------- send a message to a window ----------- */
  264. int SendMessage(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  265. {
  266.     int rtn = TRUE, x, y;
  267.     if (wnd != NULLWND)
  268.         switch (msg)    {
  269.             case PAINT:
  270.             case BORDER:
  271.             case RIGHT_BUTTON:
  272.             case LEFT_BUTTON:
  273.             case DOUBLE_CLICK:
  274.             case BUTTON_RELEASED:
  275.             case KEYBOARD:
  276.             case SHIFT_CHANGED:
  277.                 /* ------- don't send these messages unless the
  278.                     window is visible -------- */
  279.                 if (!isVisible(wnd))
  280.                     break;
  281.             default:
  282.                 rtn = wnd->wndproc(wnd, msg, p1, p2);
  283.                 break;
  284.         }
  285.     /* ----- window processor returned or the message was sent
  286.         to no window at all (NULLWND) ----- */
  287.     if (rtn != FALSE)    {
  288.         /* --------- process messages that a window sends to the
  289.             system itself ---------- */
  290.         switch (msg)    {
  291.             case STOP:
  292.                 hide_mousecursor();
  293.                 if (oldtimer != NULL)    {
  294.                     setvect(TIMER, oldtimer);
  295.                     oldtimer = NULL;
  296.                 }
  297.                 break;
  298.             /* ------- clock messages --------- */
  299.             case CAPTURE_CLOCK:
  300.                 Cwnd = wnd;
  301.                 set_timer(clocktimer, 0);
  302.                 break;
  303.             case RELEASE_CLOCK:
  304.                 Cwnd = NULLWND;
  305.                 disable_timer(clocktimer);
  306.                 break;
  307.             /* -------- keyboard messages ------- */
  308.             case KEYBOARD_CURSOR:
  309.                 if (wnd == NULLWND)
  310.                     cursor((int)p1, (int)p2);
  311.                 else
  312.                     cursor(GetClientLeft(wnd)+(int)p1,
  313.                                 GetClientTop(wnd)+(int)p2);
  314.                 break;
  315.             case CAPTURE_KEYBOARD:
  316.                 if (p2)
  317.                     ((WINDOW)p2)->PrevKeyboard=CaptureKeyboard;
  318.                 else
  319.                     wnd->PrevKeyboard = CaptureKeyboard;
  320.                 CaptureKeyboard = wnd;
  321.                 NoChildCaptureKeyboard = (int)p1;
  322.                 break;
  323.             case RELEASE_KEYBOARD:
  324.                 CaptureKeyboard = wnd->PrevKeyboard;
  325.                 NoChildCaptureKeyboard = FALSE;
  326.                 break;
  327.             case CURRENT_KEYBOARD_CURSOR:
  328.                 curr_cursor(&x, &y);
  329.                 *(int*)p1 = x;
  330.                 *(int*)p2 = y;
  331.                 break;
  332.             case SAVE_CURSOR:
  333.                 savecursor();
  334.                 break;
  335.             case RESTORE_CURSOR:
  336.                 restorecursor();
  337.                 break;
  338.             case HIDE_CURSOR:
  339.                 normalcursor();
  340.                 hidecursor();
  341.                 break;
  342.             case SHOW_CURSOR:
  343.                 if (p1)
  344.                     set_cursor_type(0x0106);
  345.                 else
  346.                     set_cursor_type(0x0607);
  347.                 unhidecursor();
  348.                 break;
  349.             /* -------- mouse messages -------- */
  350.             case MOUSE_INSTALLED:
  351.                 rtn = mouse_installed();
  352.                 break;
  353.             case SHOW_MOUSE:
  354.                 show_mousecursor();
  355.                 break;
  356.             case HIDE_MOUSE:
  357.                 hide_mousecursor();
  358.                 break;
  359.             case MOUSE_CURSOR:
  360.                 set_mouseposition((int)p1, (int)p2);
  361.                 break;
  362.             case CURRENT_MOUSE_CURSOR:
  363.                 get_mouseposition((int*)p1,(int*)p2);
  364.                 break;
  365.             case WAITMOUSE:
  366.                 waitformouse();
  367.                 break;
  368.             case TESTMOUSE:
  369.                 rtn = mousebuttons();
  370.                 break;
  371.             case CAPTURE_MOUSE:
  372.                 if (p2)
  373.                     ((WINDOW)p2)->PrevMouse = CaptureMouse;
  374.                 else
  375.                     wnd->PrevMouse = CaptureMouse;
  376.                 CaptureMouse = wnd;
  377.                 NoChildCaptureMouse = (int)p1;
  378.                 break;
  379.             case RELEASE_MOUSE:
  380.                 CaptureMouse = wnd->PrevMouse;
  381.                 NoChildCaptureMouse = FALSE;
  382.                 break;
  383.             default:
  384.                 break;
  385.         }
  386.     }
  387.     return rtn;
  388. }
  389.  
  390. /* ---- dispatch messages to the message proc function ---- */
  391. int dispatch_message(void)
  392. {
  393.     WINDOW Mwnd, Kwnd;
  394.     /* -------- collect mouse and keyboard events ------- */
  395.     collect_events();
  396.     /* --------- dequeue and process events -------- */
  397.     while (EventQueueCtr > 0)  {
  398.         struct events ev = EventQueue[EventQueueOffCtr];
  399.  
  400.         if (++EventQueueOffCtr == MAXMESSAGES)
  401.             EventQueueOffCtr = 0;
  402.         --EventQueueCtr;
  403.  
  404.         /* ------ get the window in which a
  405.                         mouse event occurred ------ */
  406.         Mwnd = inWindow(ev.mx, ev.my);
  407.  
  408.         /* ---- process mouse captures ----- */
  409.         if (CaptureMouse != NULLWND)
  410.             if (Mwnd == NULLWND ||
  411.                     NoChildCaptureMouse ||
  412.                         GetParent(Mwnd) != CaptureMouse)
  413.                 Mwnd = CaptureMouse;
  414.  
  415.         /* ------ get the window in which a
  416.                         keyboard event occurred ------ */
  417.         Kwnd = inFocus;
  418.  
  419.         /* ---- process keyboard captures ----- */
  420.         if (CaptureKeyboard != NULLWND)
  421.             if (Kwnd == NULLWND ||
  422.                     NoChildCaptureKeyboard ||
  423.                         GetParent(Kwnd) != CaptureKeyboard)
  424.                 Kwnd = CaptureKeyboard;
  425.  
  426.         /* -------- send mouse and keyboard messages to the
  427.             window that should get them -------- */
  428.         switch (ev.event)    {
  429.             case SHIFT_CHANGED:
  430.             case KEYBOARD:
  431.                 SendMessage(Kwnd, ev.event, ev.mx, ev.my);
  432.                 break;
  433.             case LEFT_BUTTON:
  434.                 if (!CaptureMouse ||
  435.                         (!NoChildCaptureMouse &&
  436.                             GetParent(Mwnd) == CaptureMouse))
  437.                     if (Mwnd != inFocus)
  438.                         SendMessage(Mwnd, SETFOCUS, TRUE, 0);
  439.             case BUTTON_RELEASED:
  440.             case DOUBLE_CLICK:
  441.             case RIGHT_BUTTON:
  442.             case MOUSE_MOVED:
  443.                 SendMessage(Mwnd, ev.event, ev.mx, ev.my);
  444.                 break;
  445.             case CLOCKTICK:
  446.                 SendMessage(Cwnd, ev.event,
  447.                     (PARAM) MK_FP(ev.mx, ev.my), 0);
  448.             default:
  449.                 break;
  450.         }
  451.     }
  452.     /* ------ dequeue and process messages ----- */
  453.     while (MsgQueueCtr > 0)  {
  454.         struct msgs mq = MsgQueue[MsgQueueOffCtr];
  455.         if (++MsgQueueOffCtr == MAXMESSAGES)
  456.             MsgQueueOffCtr = 0;
  457.         --MsgQueueCtr;
  458.         SendMessage(mq.wnd, mq.msg, mq.p1, mq.p2);
  459.         if (mq.msg == STOP || mq.msg == ENDDIALOG)
  460.                return FALSE;
  461.     }
  462.     return TRUE;
  463. }
  464.  
  465.